package pers.xiaojun.boot.module.system.service.oauth2;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import pers.xiaojun.boot.common.exception.BusinessException;
import pers.xiaojun.boot.module.system.dao.entity.oauth2.OAuth2ClientDO;
import pers.xiaojun.boot.module.system.service.oauth2.dto.OAuth2CodeDTO;
import pers.xiaojun.boot.module.system.service.oauth2.dto.OAuth2TokenDTO;
import pers.xiaojun.boot.security.util.SecurityUtils;

import java.util.List;

import static pers.xiaojun.boot.module.system.constants.BusinessCodeConstants.OAUTH2_AUTHORIZATION_CODE_INVALID;

/**
 * OAuth 2.0 授权服务实现类
 *
 * @author xiaojun
 * @since 2025-10-19
 */
@Service
@RequiredArgsConstructor
public class OAuth2GrantServiceImpl implements OAuth2GrantService {

    private final OAuth2CodeService oAuth2CodeService;
    private final OAuth2ClientService oAuth2ClientService;
    private final OAuth2TokenService oAuth2TokenService;

    @Override
    public OAuth2CodeDTO grantAuthorizationCode(String clientId, String responseType, List<String> scopes, String redirectUri, String state) {
        // 校验客户端信息
        oAuth2ClientService.checkOAuth2Client(clientId, null, responseType, redirectUri, scopes);

        // 创建授权码
        return oAuth2CodeService.createAuthorizationCode(clientId, SecurityUtils.getUserId(), scopes, redirectUri, state);
    }

    @Override
    public OAuth2TokenDTO grantTokenByAuthorizationCode(String clientId, String secret, String code) {
        // 根据 Code 获取缓存中的详细信息
        OAuth2CodeDTO oAuth2Code = oAuth2CodeService.getOAuth2CodeByCode(code);
        if (oAuth2Code == null) {
            throw new BusinessException(OAUTH2_AUTHORIZATION_CODE_INVALID);
        }
        // 创建AccessToken
        OAuth2TokenDTO accessToken = oAuth2TokenService.createAccessToken(oAuth2Code.getUserId(), clientId, secret, oAuth2Code.getScopes());
        // 创建AccessToken成功后删除缓存中的授权码
        if (accessToken != null) {
            oAuth2CodeService.deleteOAuth2CodeByCode(code);
        }
        return accessToken;
    }

    @Override
    public OAuth2TokenDTO grantTokenByRefreshToken(String refreshToken, String clientId) {
        return oAuth2TokenService.refreshAccessToken(refreshToken, clientId);
    }
}
